﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MessageWorkflow;
using MessageWorkflow.Message;

namespace SimpleConsoleExamples.Examples
{
    class TwoWayNumberCounterWithExceptionHandlingExample : IExample
    {
        Dictionary<string, int> _knownNumbers = new Dictionary<string, int>();
        WorkflowChannel _channel = new WorkflowChannel();

        private void GetAmountForWordFromCache(WorkflowAction<string> wordAction)
        {
            if (!wordAction.IsCompleted)
            {
                if (_knownNumbers.ContainsKey(wordAction.Data))
                {
                    _knownNumbers[wordAction.Data]++;
                    wordAction.IsCompleted = true;

                    _channel.Dispatch(_knownNumbers[wordAction.Data]);
                }
            }
        }
        private void GetAmountForWordFromUserAsync(WorkflowAction<string> wordAction, 
            Action callback, 
            Action<Exception> onError)
        {
            // Put on another thread, therefore similating a async call
            System.Threading.ThreadPool.QueueUserWorkItem(x =>
            {
                if (!wordAction.IsCompleted)
                {
                    Console.Write("This is a new entry! What amount should i start with (enter a invalid number to generate a ex): ");

                    int amount;

                    string amountString = Console.ReadLine();
                    if (!int.TryParse(amountString, out amount))
                    {
                        onError(new InvalidOperationException("Invalid number entered"));
                    }
                    else
                    {
                        _knownNumbers[wordAction.Data] = amount;
                        _channel.Dispatch(amount);

                        wordAction.IsCompleted = true;
                    }
                }
            });
        }

        public void Run()
        {
            Console.WriteLine("\n\nEnter a word and watch how the right components in the workflow register the amount of times you entered that specific word, if the word is new, the workflow will ask you to specify a start count");

            _channel.Subscribe(new WorkflowHandlerConfiguration(WorkflowHandlerFactory.FromLambda<WorkflowAction<string>>(GetAmountForWordFromCache))
            {
                Successors = new[] 
                {
                    new WorkflowHandlerConfiguration(WorkflowHandlerFactory.FromLambdaAsync<WorkflowAction<string>>(GetAmountForWordFromUserAsync))                
                }
            });

            while (true)
            {
                Console.Write("Enter word: ");
                string word = Console.ReadLine().ToLower();

                if (word == "x")
                    break;

                try
                {
                    int result = _channel.Dispatch(new WorkflowRequestAction<string, int>(word)).Result;
                    Console.WriteLine("For word {0}, i got number: {1}", word, result);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception found: {0}", ex.Message);
                }
            }
        }
    }
}
